import { language_convert } from "@/lang/AntDesignLang";
import { getLanguage } from "@/lang/tools";
import axios from "axios";
import { nanoid } from "nanoid";
const proxyKey = (object) => {
  const key = "diff_key";
  Object.defineProperty(object, key, {
    value: object[key] ? object[key] : nanoid(5),
    writable: false,
    enumerable: false,
    configurable: false,
  });
  return object;
};
// 一般对数组中第一层元素数据加密作为遍历的唯一key
export const addKey = (array: any[]) => {
  return array.map((item) => {
    if (isString(item) || isNumber(item) || isNull(item) || isUndefined(item)) {
      const object = {
        diff_value: item,
      };
      return proxyKey(object);
    }
    if (isObject(item)) {
      proxyKey(item);
    }
    return item;
  });
};
export const deepAddKey = (object) => {
  if (!isObject(object) && !isArray(object)) return object;
  for (const key in object) {
    const value = object[key];
    if (isObject(value)) {
      const result = proxyKey(value);
      deepAddKey(result);
    }
    if (isArray(value)) {
      deepAddKey(value);
    }
  }
  return object;
};
const httpMap = new Map();
const getHttpKey = (config: any) => {
  let { url, method, data, params } = config;
  data = isString(data) ? data : JSON.stringify(data);
  params = isString(params) ? params : JSON.stringify(params);
  return `url=${url}&method=${method}&data=${data}&params=${params}`;
};
const addHttp = (config: any) => {
  // 当请求地址，请求方式，请求参数一致时，判定为同一个请求，如果上一个请求还未完成，则拦截此次请求
  const httpKey = getHttpKey(config);
  if (httpMap.has(httpKey)) {
    const source = CancelToken.source();
    config.cancelToken = source.token;
    source.token.reason = {
      // @ts-ignore
      isNoAlert: true,
      // message: `${Date.now()}【${config.url}】有相同请求未完成，请勿重复请求`,
      message: `有重复请求`,
    };
    source.cancel();
  } else {
    httpMap.set(httpKey, true);
  }
};
const removeHttp = (config: any) => {
  if (config) {
    const httpKey = getHttpKey(config);
    httpMap.delete(httpKey);
  }
};
const clearHttp = () => {
  httpMap.clear();
};
const CancelToken = axios.CancelToken;
const request = axios.create({
  baseURL: "/api",
  timeout: 80000,
  withCredentials: true,
});

request.interceptors.request.use(
  (config: any) => {
    if (!isFormData(config.data)) {
      addHttp(config);
    }
    const token = useUserStore().token;
    const language = getLanguage();
    if (!!token) config.headers["Authorization"] = token;
    if (!!language) config.headers["i18n"] = language_convert[language];
    return config;
  },
  (error: any) => {
    Promise.reject(error);
  }
);
const errCode = [403, 900, 901, 902, 1023];
request.interceptors.response.use(
  (response: any) => {
    removeHttp(response.config);
    if (errCode.includes(+response.data.code)) {
      useUserStore().logout();
      message.destroy();
      message.warn(response.data.message);
      return Promise.reject(response.data);
    }
    const dataRes = deepAddKey(response.data);
    // return response.data;
    return dataRes;
  },
  (error: any) => {
    removeHttp(error.config);
    let errMsg = error.message;
    if (error?.response?.status === 500) {
      errMsg = error.response?.data?.message ?? error.response.statusText;
    }
    if (error?.response?.status === 403) {
      useUserStore().logout();
    }
    if (!error.isNoAlert) {
      message.error(errMsg);
    }
    return Promise.reject(error);
  }
);
axios.defaults.headers.common["Content-Type"] = "application/json";
export default request;
